<?php
/*
 * description：
 * author：wh
 * email：
 * createTime：{2024/6/10} {23:15} 
 */

namespace wanghua\general_utility_tools_php\alipay\pay;


use Alipay\EasySDK\Kernel\Config;
use Alipay\EasySDK\Kernel\Factory;
use app\common\model\TabConf;
use app\common\tools\EmailTool;
use app\index\logic\AlipayBarcodePayLogic;
use app\index\logic\CheckstandLogic;
use app\index\model\OrderModel;
use app\index\model\PartnerAccountModel;
use think\Db;
use wanghua\general_utility_tools_php\phpmailer\Exception;
use wanghua\general_utility_tools_php\tool\Tools;

/**
 * 支付宝面对面扫码支付（用户出示付款码）
 *
 * 【扫码支付专用】
 *
 * 依赖："alipaysdk/easysdk": "^2.2" || composer require alipaysdk/easysdk
 *
 * Class AlipayScanPay
 * @package wanghua\general_utility_tools_php\alipay\transfer
 */
class AlipayScanPay
{
    /**
     * 支付参数配置
     * @var array
     */
    private array $config = [];

    function __construct($config)
    {
        /** 设置支付参数 */
        $this->config = $config;
    }

    /**
     * desc：面对面扫码支付-（扫用户的付款码）
     *
     * 注意：
     * 免密支付是同步返回支付结果，输入密码支付是异步通知支付结果，
     * 所以需要处理异步支付结果通知。
     * @param array $order 订单信息
     * @param string $auth_code 扫码枪扫描后的授权码
     * @return array 返回支付结果（一维数组）
     */
    function scanPay($order,$auth_code){
        if(empty($auth_code)){
            return Tools::set_res(500,'授权码错误');
        }
        try {
            //1. 设置参数（全局只需设置一次）
            Factory::setOptions($this->getOptions());
            //2. 发起API调用（以支付能力下的统一收单交易创建接口为例）
            $result = Factory::payment()->faceToFace()
                ->optional('scene','bar_code')
                ->pay($order['title'], $order['orderid'], $order['real_amount'], $auth_code);

            if($result->code == 10003){
                return Tools::set_res(230,'交易进行中（提示用户输入密码）'.$result->msg);
            }
            //必须解析json
            $resp = json_decode($result->httpBody, true);
            //支付宝面对面扫码支付后续流程
            return Tools::set_ok('ok',$resp['alipay_trade_pay_response']);//返回支付结果（一维数组）
        } catch (\Exception $e) {
            $err_data = [
                'error'=>'支付宝付款码支付错误'.$e->getMessage(),
                'error_info'=>$e->getTraceAsString()
            ];
            Tools::log_to_write_txt($err_data);
            return Tools::set_fail('错误.'.$e->getMessage());
        }
    }


    /**
     * desc：获取支付配置
     * author：wh
     * @return Config
     * @throws Exception
     */
    private function getOptions()
    {
        if(empty($this->config)){
            throw new Exception('支付宝配置错误');
        }
        if(empty($this->config['notifyUrl'])){
            throw new Exception('支付宝配置错误：notifyUrl通知地址字段必须配置（免密支付是同步返回支付结果，输入密码支付是异步通知支付结果）');
        }
        $config = $this->config;
        $options = new Config();
        $options->protocol = 'https';
        $options->gatewayHost = 'openapi.alipay.com';
        $options->signType = $config['sign_type'];

        $options->appId = $config['app_id'];//'<-- 请填写您的AppId，例如：2019022663440152 -->';

        // 为避免私钥随源码泄露，推荐从文件中读取私钥字符串而不是写入源码中
        $options->merchantPrivateKey = $config['alipay_app_private_key'];//'<-- 请填写您的应用私钥，例如：MIIEvQIBADANB ... ... -->';

        $options->alipayCertPath = Tools::get_root_path().$config['cert_path_alipayCertPublicKey_RSA2'];//'<-- 请填写您的支付宝公钥证书文件路径，例如：/foo/alipayCertPublicKey_RSA2.crt -->';
        $options->alipayRootCertPath = Tools::get_root_path().$config['cert_path_alipayRootCert'];//'<-- 请填写您的支付宝根证书文件路径，例如：/foo/alipayRootCert.crt" -->';
        $options->merchantCertPath = Tools::get_root_path().$config['appCertPublicKey'];//'<-- 请填写您的应用公钥证书文件路径，例如：/foo/appCertPublicKey_2019051064521003.crt -->';

        //注：如果采用非证书模式，则无需赋值上面的三个证书路径，改为赋值如下的支付宝公钥字符串即可
        // $options->alipayPublicKey = '<-- 请填写您的支付宝公钥，例如：MIIBIjANBg... -->';

        //可设置异步通知接收服务地址（可选）
        $options->notifyUrl = $this->config['notifyUrl'];//request()->domain().'/index/alipay/notify';//"<-- 请填写您的支付类接口异步通知接收服务地址，例如：https://www.test.com/callback -->";

        return $options;
    }


    /**
     * desc：支付宝扫码异步通知
     *
     * 【通知结果是一维数组】
     *
     * {"gmt_create":"2024-06-10 11:53:37","charset":"UTF-8","seller_email":"15023017325",
     * "subject":"购物消费",
     * "sign":"oCR3X0ViRrydigLMeOCTrMBNx7O8bSZnEflT0qZYo0gXk2jTI2OVB9mG2UPCkGuSND3wq/pMRFN
     * ljuz+2r3KMha9a6ArD/ey8w1am3yCKI+FMqUMQSv9TJqfpWdAsc8B45egtr+txBBOA1NMfN41hPnTxM3QzQ82cm
     * 7VYw6pnYpxJVj/3AsqYxY+wcyMq5+v25eC4TgBo+YJ9pfb3rqaAV91cJBoHRq1Cwh0XEnOzm9zpv7b5cu3r+V0oeW
     * wTCCi8S1TXW2dfE4H8o63xgASYfJO2fgGIu19YICQdUONkDhu9Tfbf3fFf9SHw3RIw8zrQRqkwAXC32NwfUv4Ru5NqQ==",
     * "buyer_id":"2088612757425274","invoice_amount":"3258.60","notify_id":"2024061001222115350025271439748729",
     * "fund_bill_list":"[{\"amount\":\"3258.60\",\"fundChannel\":\"ALIPAYACCOUNT\"}]",
     * "notify_type":"trade_status_sync","trade_status":"TRADE_SUCCESS","receipt_amount":"3258.60",
     * "app_id":"2021004136614333","buyer_pay_amount":"3258.60","sign_type":"RSA2",
     * "seller_id":"2088642975857443","gmt_payment":"2024-06-10 11:53:50",
     * "notify_time":"2024-06-10 12:07:40","version":"1.0","out_trade_no":"cs25obpv1717991615660",
     * "total_amount":"3258.60","trade_no":"2024061022001425271426453509","auth_app_id":"2021004136614333",
     * "buyer_logon_id":"146***@qq.com","point_amount":"0.00"}
     *
     * author：wh
     * param function $fn 传入订单处理逻辑函数 要求返回success、fail
     * @return string
     */
    function scanPayNotify($fn){
        Tools::log_to_write_txt([
            '支付宝异步通知',
            'input'=>input()
        ]);

        $out_trade_no = input('out_trade_no');
        if(empty($out_trade_no)){
            Tools::log_to_write_txt(['error'=>'out_trade_no为空,文件:'.__FILE__.',line:'.__LINE__]);
            return '';
        }
        //$order = Db::table(TabConf::$fa_order)
        //    ->where('orderid',$out_trade_no)
        //    ->find();
        //if(empty($order)){
        //    Tools::log_to_write_txt(['error'=>'订单不存在,文件:'.__FILE__.',line:'.__LINE__]);
        //    return '';
        //}
        //该字段用于判断成功、失败
        $trade_status = input('trade_status');
        if(empty($trade_status)){
            Tools::log_to_write_txt(['error'=>'trade_status为空,文件:'.__FILE__.',line:'.__LINE__]);
            return '';
        }
        if(empty($this->config['seller_id'])){
            Tools::log_to_write_txt(['error'=>'卖家seller_id为空,文件:'.__FILE__.',line:'.__LINE__]);
            return '';
        }

        //判断来源
        $seller_id = input('seller_id');
        if($seller_id != $this->config['seller_id']){
            Tools::log_to_write_txt(['error'=>'支付通知来源错误','seller_id'=>$seller_id,'config'=>$this->config['seller_id']]);
            return 'fail';
        }
        //支付宝面对面扫码支付后续流程
        $result = input();
        //异步通知
        //$res = CheckstandLogic::alipayScanSuccessFlow($result,$order);
        //if($res['code'] == 200 || $res['code'] == 230){//成功或进行中
        //    return 'success';
        //}
        return $fn($result);//要求返回success、fail
    }
}